#pragma once
#include "CInterlockedReferenceCount.h"
#include "CNotifyOnDelete.h"
#include "IntrusiveList.h"
#include "IPALStagingTexture.h"
#include "xchainedmap.h"


class HWTexture;
class HWTextureManager;

class CTiledSurface :
	public CInterlockedReferenceCount,
	public CNotifyOnDelete

{

private:  
	CTiledSurface();
public: 
	CTiledSurface(XINT32 width, XINT32 height, XBOOL isOpaque);
protected: 
	virtual ~CTiledSurface();
public:
	struct Tile
	{
	public: 
		xref_ptr<HWTexture> spCompositorTexture;
		xref_ptr<IPALStagingTexture> spStagingTexture;
		struct XRECT_WH bounds;
		XUINT64 timeStamp;
		struct IntrusiveList<Tile>::ListEntry tempListEntry; 
		XBOOL shouldInitializeToTransparent;
		XUINT64 GetAllocationSize();
	};


public: 
	XUINT32 GetTileCount();
	xchainedmap<XPOINT,Tile *>::const_iterator Begin();
	xchainedmap<XPOINT,Tile *>::const_iterator End();
	HRESULT UpdateSurfaceFromSoftware(HWTextureManager * pTextureManager, struct IPALSurface * pSurface);
	HRESULT AddTile(struct XPOINT origin, XUINT64 timestamp, XBOOL initializeToTransparent, struct XSIZE size);
	void FreeTile(struct Tile * pTile);
	void FreeAllTiles();
	struct Tile * GetTile(const struct XPOINT & origin);
	HRESULT Resize(XINT32 newWidth, XINT32 newHeight, struct IPALRegion * pValidRegion);
	XUINT32 GetAAMask(const struct Tile * pTile);
	HRESULT EnsureTileTexture(HWTextureManager * pTextureManager, XBOOL usePermanentAtlas, XBOOL hasSoftwareBits, struct Tile * pTile);
	HRESULT ClearRect(struct Tile * pTile, const struct XRECT_WH * pRect);
	HRESULT SubmitTileUpdate(struct IPALSurfaceUpdate * pSurfaceUpdate, struct Tile * pTile, const struct XRECT_WH * pUpdateIntersection, XBOOL crossAdapterUpdate);
	XBOOL IsOpaque();
	XINT32 GetWidth();
	XINT32 GetHeight();
	XBOOL IsLost();
	void GetClippedTileBounds(struct XPOINT origin, struct XRECT_WH * pBounds);
private: 
	static HRESULT AddSurfaceUpdate(struct IPALSurfaceUpdate * pSurfaceUpdate, HWTexture * pDstTexture, const struct XPOINT * pDstPoint, const struct XRECT_WH * pSrcRect, XBOOL crossAdapterUpdate);
	HRESULT UpdateTileFromSoftware(HWTextureManager * pTextureManager, struct Tile * pTile, XUINT8 * pbSource, XINT32 nStrideSource, XUINT32 uWidthSource, XUINT32 uHeightSource, const struct XPOINT & origin);
	HRESULT EnsureTiles();
public: 
	static XBOOL NeedsToBeTiled(struct XSIZE size, HWTextureManager * pTextureManager);
	static XINT32 AlignToTilesRoundDown(XINT32 in);
	static XINT32 AlignToTilesRoundUp(XINT32 in);
	static void AlignToTiles(struct XRECT_WH * pAlignedRect, const struct XRECT_WH * pRect);
	static void AlignToTiles(struct XRECT_RB * pAlignedRect, const struct XRECT_RB * pRect);
private: 
	xchainedmap<XPOINT,Tile *> m_tiles;
	XINT32 m_tiledWidth;
	XINT32 m_tiledHeight;
	XBOOL m_isOpaque;
};
